﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Reactor.Client.Controls
{
    [ContentProperty("Text")]
    public sealed class PixelText : Panel
    {
        private static readonly DependencyProperty TextProperty;
        public static readonly DependencyProperty ColorProperty;
        public static readonly DependencyProperty FontProperty;

        static PixelText()
        {
            TextProperty = DependencyProperty.Register("Text", typeof(String), typeof(PixelText), new PropertyMetadata((string)null));
            ColorProperty = DependencyProperty.Register("Color", typeof(Color), typeof(PixelText), new PropertyMetadata(Colors.Black));
            FontProperty = DependencyProperty.Register("Font", typeof(PixelFont), typeof(PixelText), new PropertyMetadata(PixelFont.Pf11Px));
        }

        public string Text
        {
            get
            {
                return (string)GetValue(TextProperty);
            }
            set
            {
                SetValue(TextProperty, value);
            }
        }

        public Color Color
        {
            get
            {
                return (Color)GetValue(ColorProperty);
            }
            set
            {
                SetValue(ColorProperty, value);
            }
        }

        public PixelFont Font
        {
            get
            {
                return (PixelFont)GetValue(FontProperty);
            }
            set
            {
                SetValue(FontProperty, value);
            }
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            var font = PixelFonts.Fonts[Font];

            var chars = Text.ToCharArray().Where(x => font.Any(c => c.Key == x)).Select(x => new Tuple<char, int>(x, font[x].GetLength(0))).ToArray();

            var width = chars.Select(x => x.Item2).Aggregate((x, y) => x + y);
            var height = font.First().Value.GetLength(1);

            var bitmap = new WriteableBitmap(width, height);

            var color = Color.A << 24 | Color.R << 16 | Color.G << 8 | Color.B;

            var offset = 0;

            for (int i = 0; i < chars.Length; i++)
            {
                var bytes = font[chars[i].Item1];

                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < bytes.GetLength(0); x++)
                    {
                        if (bytes[x, y])
                        {
                            var index = y * width + offset + x;
                            bitmap.Pixels[index] = color;
                        }
                    }
                }

                offset += chars[i].Item2;
            }

            bitmap.Invalidate();
            var image = new Image { Source = bitmap, Width = bitmap.PixelWidth, Height = bitmap.PixelHeight };
            Children.Add(image);

            Size panelDesiredSize = new Size();

            foreach (UIElement child in Children)
            {
                child.Measure(availableSize);
                panelDesiredSize = child.DesiredSize;
            }

            return panelDesiredSize;
        }
        protected override Size ArrangeOverride(Size finalSize)
        {
            foreach (UIElement child in Children)
            {
                child.Arrange(new Rect(new Point(0, 0), child.DesiredSize));
            }
            return finalSize;
        }
    }
}
